<template>
  <div class="rich-editor-container">
    <div ref="editorEl" class="editor-wrapper"></div>
  </div>
</template>

<script lang="ts" setup>
import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue'
import Quill from 'quill'
import 'quill/dist/quill.snow.css'

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  placeholder: {
    type: String,
    default: '请输入内容...'
  },
  disabled: {
    type: Boolean,
    default: false
  },
  allowedTags: {
    type: Array,
    default: () => ['p', 'h1', 'h2', 'h3', 'strong', 'em', 'u', 's', 'a', 'ul', 'ol', 'li', 'blockquote', 'code']
  }
})

const emit = defineEmits(['update:modelValue', 'ready', 'error'])

const editorEl = ref<HTMLElement | null>(null)
const quill = shallowRef<Quill | null>(null)
const isEditorReady = ref(false)

// 基本HTML净化函数（替代dompurify）
const sanitizeHTML = (html: string): string => {
  if (!html) return ''
  
  try {
    // 创建临时div来解析HTML
    const div = document.createElement('div')
    div.innerHTML = html
    
    // 移除非允许标签
    const elements = Array.from(div.querySelectorAll('*'))
    elements.forEach(el => {
      if (!props.allowedTags.includes(el.tagName.toLowerCase())) {
        el.outerHTML = el.innerHTML // 移除非允许标签但保留内容
      }
      
      // 移除危险属性
      Array.from(el.attributes).forEach(attr => {
        if (attr.name.startsWith('on') || ['src', 'href', 'style'].includes(attr.name)) {
          el.removeAttribute(attr.name)
        }
      })
    })
    
    return div.innerHTML
  } catch (error) {
    console.error('HTML净化失败:', error)
    emit('error', error)
    return ''
  }
}

// 工具栏配置
const toolbarOptions = [
  [{ 'header': [1, 2, 3, false] }],
  ['bold', 'italic', 'underline', 'strike'],
  [{ 'color': [] }, { 'background': [] }],
  [{ 'align': [] }],
  ['blockquote', 'code-block'],
  [{ 'list': 'ordered' }, { 'list': 'bullet' }],
  ['link'],
  ['clean']
]

// 安全设置内容
const setContent = (html: string) => {
  if (!quill.value) return
  
  try {
    quill.value.enable(false)
    const cleanHTML = sanitizeHTML(html)
    const delta = quill.value.clipboard.convert(cleanHTML)
    quill.value.setContents(delta)
    quill.value.enable(!props.disabled)
  } catch (error) {
    console.error('设置内容失败:', error)
    emit('error', error)
  }
}

// 获取内容
const getContent = (): string => {
  if (!quill.value) return ''
  try {
    return editorEl.value?.querySelector('.ql-editor')?.innerHTML || ''
  } catch (error) {
    console.error('获取内容失败:', error)
    emit('error', error)
    return ''
  }
}

// 安全插入内容
const insertContent = (content: string, index?: number) => {
  if (!quill.value || !isEditorReady.value) return false
  
  try {
    const cleanContent = sanitizeHTML(content)
    const insertionIndex = index ?? quill.value.getSelection()?.index ?? quill.value.getLength()
    
    quill.value.insertText(insertionIndex, '\n')
    quill.value.clipboard.dangerouslyPasteHTML(insertionIndex + 1, cleanContent)
    quill.value.setSelection(insertionIndex + cleanContent.length + 2, 0)
    return true
  } catch (error) {
    console.error('插入内容失败:', error)
    emit('error', error)
    return false
  }
}

// 初始化编辑器
const initializeEditor = () => {
  if (!editorEl.value) return

  try {
    quill.value = new Quill(editorEl.value, {
      theme: 'snow',
      modules: {
        toolbar: toolbarOptions
      },
      placeholder: props.placeholder,
      readOnly: props.disabled
    })

    // 设置初始内容
    if (props.modelValue) {
      setContent(props.modelValue)
    }

    const handleTextChange = () => {
      emit('update:modelValue', getContent())
    }

    quill.value.on('text-change', handleTextChange)
    
    nextTick(() => {
      isEditorReady.value = true
      emit('ready', quill.value)
    })

    return () => {
      quill.value?.off('text-change', handleTextChange)
    }
  } catch (error) {
    console.error('编辑器初始化失败:', error)
    emit('error', error)
    return null
  }
}

// 监听状态变化
watch(() => props.disabled, (disabled) => {
  if (quill.value) {
    quill.value.enable(!disabled)
  }
})

watch(() => props.modelValue, (newVal) => {
  if (newVal !== getContent()) {
    const handler = quill.value?.emitter.listeners('text-change')
    quill.value?.off('text-change')
    setContent(newVal)
    nextTick(() => {
      handler?.forEach(h => quill.value?.on('text-change', h))
    })
  }
})

onMounted(() => {
  const cleanup = initializeEditor()
  
  onUnmounted(() => {
    cleanup?.()
    quill.value = null
    isEditorReady.value = false
  })
})

defineExpose({
  quillInstance: quill,
  insertContent,
  getContent,
  setContent,
  focus: () => {
    try {
      quill.value?.focus()
    } catch (error) {
      console.error('聚焦失败:', error)
    }
  },
  isReady: isEditorReady
})
</script>

<style scoped>
/* 保持之前的样式不变 */
.rich-editor-container {
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.3s ease;
}

.rich-editor-container:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.editor-wrapper {
  height: 400px;
  background: white;
}

/* 限定样式作用域 */
:deep(.rich-editor-container .ql-toolbar) {
  border: none !important;
  background-color: #f8f9fa;
  border-bottom: 1px solid #e9ecef !important;
  border-radius: 8px 8px 0 0;
}

:deep(.rich-editor-container .ql-container) {
  border: none !important;
  font-family: 'Helvetica Neue', Arial, sans-serif;
  font-size: 16px;
  border-radius: 0 0 8px 8px;
}

:deep(.rich-editor-container .ql-editor) {
  padding: 16px;
  min-height: 300px;
  line-height: 1.6;
  color: #333 !important;
}

/* 按钮样式 */
:deep(.rich-editor-container .ql-snow .ql-picker-label:hover),
:deep(.rich-editor-container .ql-snow .ql-picker-item:hover),
:deep(.rich-editor-container .ql-snow button:hover) {
  color: #4361ee !important;
}

:deep(.rich-editor-container .ql-snow .ql-active),
:deep(.rich-editor-container .ql-snow .ql-toolbar button.ql-active) {
  color: #4361ee !important;
}
</style>